import iconFont from '@/assets/iconFont/iconfont.less';
import loginBg from '@/assets/img/login_bg.png';
import Logo from '@/assets/img/logo.png';
import AppDownloadQRCode from '@/components/AppDownloadQRCode';
import Footer from '@/components/Footer';
import type { ProFormInstance } from '@/components/Pro/';
import { authControllerGetCaptcha } from '@/services/auth/auth';
import { sysLoginControllerLogin as login } from '@/services/login/sysLogin';
import { setTokenInfo } from '@/utils';
import { LoginForm, ProFormText } from '@ant-design/pro-components';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import { Helmet, history, useIntl, useModel } from '@umijs/max';
import { Alert, Button, Flex, message, theme } from 'antd';
import cls from 'classnames';
import CryptoJS from 'crypto-js/crypto-js';
import JSEncrypt from 'jsencrypt';
import React, { useEffect, useRef, useState } from 'react';
import { flushSync } from 'react-dom';
import { AESKey, RESKey } from './encryptKey';

// 初始化
const keyPair = new JSEncrypt();

/**
 * AES加密
 * @param content
 * @returns {string}
 * @constructor
 */
const AESEncryption = (content: string) => {
  const aesContent = CryptoJS.enc.Utf8.parse(content);
  const key = CryptoJS.enc.Utf8.parse(AESKey.key);
  const iv = CryptoJS.enc.Utf8.parse(AESKey.iv);
  const encrypted = CryptoJS.AES.encrypt(aesContent, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  });
  return encrypted.toString();
};

/**
 *RSA加密
 * @returns
 */
const encryptByRsa = (content: string) => {
  keyPair.setPublicKey(RESKey);
  return keyPair.encrypt(AESEncryption(content));
};

const { useToken } = theme;

interface SubmitProps {
  username: string;
  password: string;
}

const LoginMessage: React.FC<{
  content: string;
}> = ({ content }) => {
  return (
    <Alert
      style={{
        marginBottom: 24,
      }}
      message={content}
      type="error"
      showIcon
    />
  );
};
const Login: React.FC = () => {
  const formRef = useRef<ProFormInstance>();
  const [captchaInfo, setCaptchaInfo] = useState({});
  const [userLoginState, setUserLoginState] = useState<API.LoginResult>({});
  const { initialState, setInitialState } = useModel('@@initialState');
  const intl = useIntl();
  const getCaptchaData = () => {
    authControllerGetCaptcha({
      skipErrorHandler: true,
      token: '',
    }).then((res) => {
      setCaptchaInfo(res.data || {});
    });
  };

  useEffect(() => {
    getCaptchaData();
  }, []);

  const { token } = useToken();
  const containerWrapperClassName = useEmotionCss(() => {
    return {
      position: 'relative',
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'flex-end',
      flexDirection: 'column',
      height: '100vh',
      overflow: 'auto',
      backgroundImage: `url(${loginBg})`,
      backgroundSize: 'cover',
      backgroundPosition: 'center',
    };
  });
  const containerClassName = useEmotionCss(() => {
    return {
      display: 'flex',
      flexDirection: 'column',
      width: '630px',
      minWidth: 450,
      height: '100%',
      background: 'rgba(255,255,255,0.71)',
      '@media screen and (max-width: 768px)': {
        width: '100%',
        minWidth: '100%',
      },
      '.captchBtn': {
        flex: 1,
        paddingInline: 6,
        background: '#EDEDED',
      },
      '.captchBtn.ant-btn-default:not(:disabled):not(.ant-btn-disabled):hover': {
        border: '1px solid #e5e6ea',
        background: '#EDEDED',
      },
      '.ant-input-outlined': {
        background: '#EDEDED',
        border: '1px solid #e5e6ea',
        fontSize: 14,
        '.ant-input-prefix': {
          marginInlineEnd: 10,
        },
        'input:-webkit-autofill': {
          backgroundColor: 'transparent !important',
          backgroundImage: 'none !important',
          boxShadow: '0 0 0 1000px #EDEDED inset !important',
          fontSize: 14,
        },
      },
      '.ant-input-outlined:focus-within': {
        boxShadow: '0 0 0 1px #e5e6ea !important',
      },
      '.ant-input-outlined:focus': {
        boxShadow: '0 0 0 1px #e5e6ea !important',
      },
      '.ant-input-affix-wrapper-lg': {
        paddingBlock: 8,
      },
      '.ant-btn': {
        border: '1px solid #e5e6ea',
      },
      '.ant-btn-primary:disabled': {
        background: '#EDEDED',
      },
    };
  });
  const logoClassName = useEmotionCss(() => {
    return {
      position: 'absolute',
      top: 58,
      left: 62,
      display: 'flex',
      alignItems: 'center',
      h1: {
        margin: 0,
        marginLeft: 8,
        fontWeight: 600,
        fontSize: 24,
      },
    };
  });
  const iconClassName = useEmotionCss(() => {
    return {
      color: '#5A5D64',
      fontSize: 18,
    };
  });
  const sloganClassName = useEmotionCss(() => {
    return {
      position: 'absolute',
      bottom: 57,
      left: 110,
      color: token.colorPrimary,
      fontSize: 14,
    };
  });
  const fetchUserInfo = async () => {
    const userInfo = await initialState?.fetchUserInfo?.();
    if (userInfo) {
      const stationInfo = userInfo?.tenants[0]?.stationInfos?.[0];
      flushSync(() => {
        setInitialState((s) => ({
          ...s,
          ...userInfo,
          isPhotovoltaic: stationInfo?.stationType === '6' || stationInfo?.stationType === '2',
          oldStation: stationInfo?.oldStation,
          uiVersion: stationInfo?.uiVersion,
          stationCode: stationInfo?.stationCode,
          isArea: stationInfo?.isArea,
        }));
      });
    }
  };
  const handleSubmit = async (values: SubmitProps) => {
    try {
      // 登录
      const msg = await login(
        {
          ...values,
          username: encryptByRsa(values.username),
          password: encryptByRsa(values.password),
          captchaCacheId: captchaInfo.captchaId,
          grant_type: 'captcha',
          scope: 'openid',
        },
        {
          skipErrorHandler: true,
        },
      );
      if (msg.success) {
        const defaultLoginSuccessMessage = intl.formatMessage({ id: 'login.loginSuccess' });
        message.success(defaultLoginSuccessMessage);
        setTokenInfo(msg.data);
        await fetchUserInfo();
        //const urlParams = new URL(window.location.href).searchParams;
        history.push('/');
        return;
      } else {
        getCaptchaData();
      }
      setUserLoginState(msg);
    } catch (error) {
      setUserLoginState({ message: intl.formatMessage({ id: 'login.sysPrompt' }) });
    }
  };

  const { username, password, captchaCode } = formRef?.current?.getFieldsValue() || {};

  return (
    <div className={containerWrapperClassName}>
      <div className={logoClassName}>
        <img src={Logo} />
      </div>
      <div className={sloganClassName}>Smart Energy Strorage Cloud Platform</div>
      <div className={containerClassName}>
        <Helmet>
          <title>
            {intl.formatMessage({ id: 'login.loginBtn' })} -{' '}
            {intl.formatMessage({ id: 'login.poster' })}
          </title>
        </Helmet>
        <div
          style={{
            flex: '1',
            paddingTop: 60,
          }}
        >
          <LoginForm
            submitter={{
              submitButtonProps: {
                disabled: username && password && captchaCode ? false : true,
              },
            }}
            formRef={formRef}
            contentStyle={{
              width: 310,
              minWidth: 280,
              maxWidth: '75vw',
            }}
            title={intl.formatMessage({ id: 'login.poster' })}
            initialValues={{
              autoLogin: true,
            }}
            onFinish={async (values) => {
              await handleSubmit(values as SubmitProps);
            }}
            onValuesChange={() => {
              setUserLoginState({});
            }}
          >
            <>
              <ProFormText
                name="username"
                fieldProps={{
                  size: 'large',
                  prefix: (
                    <span
                      className={cls(iconFont.iconfont, iconClassName)}
                      dangerouslySetInnerHTML={{ __html: '&#xe8f1;' }}
                    ></span>
                  ),
                }}
                placeholder={intl.formatMessage({ id: 'login.enter' })}
                rules={[
                  {
                    required: true,
                    message: intl.formatMessage({ id: 'login.usrRequ' }),
                  },
                ]}
              />
              <ProFormText.Password
                name="password"
                fieldProps={{
                  size: 'large',
                  prefix: (
                    <span
                      className={cls(iconFont.iconfont, iconClassName)}
                      dangerouslySetInnerHTML={{ __html: '&#xe8f2;' }}
                    ></span>
                  ),
                }}
                placeholder={intl.formatMessage({ id: 'login.passWord' })}
                rules={[
                  {
                    required: true,
                    message: intl.formatMessage({ id: 'login.passRequ' }),
                  },
                ]}
              />
            </>
            <Flex gap={8}>
              <ProFormText
                name="captchaCode"
                fieldProps={{
                  size: 'large',
                  prefix: (
                    <span
                      className={cls(iconFont.iconfont, iconClassName)}
                      dangerouslySetInnerHTML={{ __html: '&#xe8f3;' }}
                    ></span>
                  ),
                }}
                placeholder={intl.formatMessage({ id: 'login.code' })}
                rules={[
                  {
                    required: true,
                    message: intl.formatMessage({ id: 'login.codeRequ' }),
                  },
                ]}
                width={156}
              />
              <Button onClick={() => getCaptchaData()} className="captchBtn" size="large">
                <img src={captchaInfo.captchaBase64} />
              </Button>
            </Flex>
            {userLoginState.message && <LoginMessage content={userLoginState.message} />}
          </LoginForm>
        </div>
        <AppDownloadQRCode />
        <Footer />
      </div>
    </div>
  );
};
export default Login;
